"""
RedFire 数据转换器
================

提供统一的数据格式转换功能，支持不同数据源间的数据格式转换。
"""

from typing import Dict, List, Optional, Any, Union
from dataclasses import dataclass
from datetime import datetime
import logging

from .models import MarketDataTick, MarketDataBar, ContractInfo


@dataclass
class ConversionConfig:
    """转换配置"""
    source_format: str
    target_format: str
    field_mapping: Dict[str, str]
    data_validation: bool = True
    timestamp_format: str = "%Y-%m-%d %H:%M:%S"


class RedFireDataConverter:
    """
    RedFire数据转换器
    
    提供统一的数据格式转换功能，支持：
    - 不同数据源格式转换
    - 字段映射和转换
    - 数据验证
    - 时间戳格式统一
    """
    
    def __init__(self, config: Optional[ConversionConfig] = None):
        """
        初始化数据转换器
        
        Args:
            config: 转换配置
        """
        self.config = config or ConversionConfig(
            source_format="raw",
            target_format="redfire",
            field_mapping={}
        )
        self.logger = logging.getLogger("redfire.data_converter")
        
        # 默认字段映射
        self.default_mappings = {
            "ctp": {
                "symbol": "InstrumentID",
                "price": "LastPrice",
                "volume": "Volume",
                "timestamp": "UpdateTime",
                "bid_price": "BidPrice1",
                "ask_price": "AskPrice1",
                "bid_volume": "BidVolume1",
                "ask_volume": "AskVolume1"
            },
            "tushare": {
                "symbol": "ts_code",
                "price": "close",
                "volume": "vol",
                "timestamp": "trade_date",
                "open": "open",
                "high": "high",
                "low": "low",
                "close": "close"
            }
        }
    
    async def convert_tick_data(self, raw_data: Dict[str, Any], 
                               source_format: str = "raw") -> Optional[MarketDataTick]:
        """
        转换Tick数据
        
        Args:
            raw_data: 原始数据
            source_format: 源数据格式
            
        Returns:
            MarketDataTick: 转换后的Tick数据
        """
        try:
            # 获取字段映射
            field_mapping = self._get_field_mapping(source_format)
            
            # 提取字段
            symbol = self._extract_field(raw_data, field_mapping, "symbol")
            price = self._extract_field(raw_data, field_mapping, "price", float)
            volume = self._extract_field(raw_data, field_mapping, "volume", int, 0)
            timestamp = self._extract_timestamp(raw_data, field_mapping)
            
            # 可选字段
            bid_price = self._extract_field(raw_data, field_mapping, "bid_price", float)
            ask_price = self._extract_field(raw_data, field_mapping, "ask_price", float)
            bid_volume = self._extract_field(raw_data, field_mapping, "bid_volume", int, 0)
            ask_volume = self._extract_field(raw_data, field_mapping, "ask_volume", int, 0)
            
            # 数据验证
            if not symbol or price is None or price <= 0:
                self.logger.warning(f"Tick数据验证失败: {raw_data}")
                return None
            
            # 创建Tick数据
            tick = MarketDataTick(
                symbol=symbol,
                price=price,
                volume=volume,
                timestamp=timestamp,
                bid_price=bid_price,
                ask_price=ask_price,
                bid_volume=bid_volume,
                ask_volume=ask_volume
            )
            
            return tick
            
        except Exception as e:
            self.logger.error(f"Tick数据转换失败: {e}")
            return None
    
    async def convert_bar_data(self, raw_data: Dict[str, Any], 
                              source_format: str = "raw") -> Optional[MarketDataBar]:
        """
        转换K线数据
        
        Args:
            raw_data: 原始数据
            source_format: 源数据格式
            
        Returns:
            MarketDataBar: 转换后的K线数据
        """
        try:
            # 获取字段映射
            field_mapping = self._get_field_mapping(source_format)
            
            # 提取字段
            symbol = self._extract_field(raw_data, field_mapping, "symbol")
            open_price = self._extract_field(raw_data, field_mapping, "open", float)
            high_price = self._extract_field(raw_data, field_mapping, "high", float)
            low_price = self._extract_field(raw_data, field_mapping, "low", float)
            close_price = self._extract_field(raw_data, field_mapping, "close", float)
            volume = self._extract_field(raw_data, field_mapping, "volume", int, 0)
            timestamp = self._extract_timestamp(raw_data, field_mapping)
            
            # 数据验证
            if not symbol or not all(p is not None and p > 0 for p in [open_price, high_price, low_price, close_price]):
                self.logger.warning(f"K线数据验证失败: {raw_data}")
                return None
            
            # OHLC关系验证
            if high_price < max(open_price, close_price) or low_price > min(open_price, close_price):
                self.logger.warning(f"K线数据OHLC关系错误: {raw_data}")
                return None
            
            # 创建K线数据
            bar = MarketDataBar(
                symbol=symbol,
                open=open_price,
                high=high_price,
                low=low_price,
                close=close_price,
                volume=volume,
                timestamp=timestamp
            )
            
            return bar
            
        except Exception as e:
            self.logger.error(f"K线数据转换失败: {e}")
            return None
    
    async def convert_contract_data(self, raw_data: Dict[str, Any], 
                                   source_format: str = "raw") -> Optional[ContractInfo]:
        """
        转换合约数据
        
        Args:
            raw_data: 原始数据
            source_format: 源数据格式
            
        Returns:
            ContractInfo: 转换后的合约数据
        """
        try:
            # 获取字段映射
            field_mapping = self._get_field_mapping(source_format)
            
            # 提取字段
            symbol = self._extract_field(raw_data, field_mapping, "symbol")
            name = self._extract_field(raw_data, field_mapping, "name", str, symbol)
            exchange = self._extract_field(raw_data, field_mapping, "exchange")
            product_type = self._extract_field(raw_data, field_mapping, "product_type")
            size = self._extract_field(raw_data, field_mapping, "size", int, 1)
            price_tick = self._extract_field(raw_data, field_mapping, "price_tick", float, 0.01)
            
            # 数据验证
            if not symbol:
                self.logger.warning(f"合约数据验证失败: {raw_data}")
                return None
            
            # 创建合约数据
            contract = ContractInfo(
                symbol=symbol,
                name=name,
                exchange=exchange,
                product_type=product_type,
                size=size,
                price_tick=price_tick
            )
            
            return contract
            
        except Exception as e:
            self.logger.error(f"合约数据转换失败: {e}")
            return None
    
    def _get_field_mapping(self, source_format: str) -> Dict[str, str]:
        """获取字段映射"""
        if source_format in self.default_mappings:
            return self.default_mappings[source_format]
        elif self.config.field_mapping:
            return self.config.field_mapping
        else:
            return {}
    
    def _extract_field(self, data: Dict[str, Any], mapping: Dict[str, str], 
                      field_name: str, data_type: type = str, default: Any = None) -> Any:
        """提取字段值"""
        # 获取映射的字段名
        mapped_field = mapping.get(field_name, field_name)
        
        # 提取值
        value = data.get(mapped_field, default)
        
        # 类型转换
        if value is not None and data_type != str:
            try:
                return data_type(value)
            except (ValueError, TypeError):
                return default
        
        return value
    
    def _extract_timestamp(self, data: Dict[str, Any], mapping: Dict[str, str]) -> datetime:
        """提取时间戳"""
        timestamp_field = mapping.get("timestamp", "timestamp")
        timestamp_value = data.get(timestamp_field)
        
        if timestamp_value is None:
            return datetime.now()
        
        # 尝试解析时间戳
        if isinstance(timestamp_value, datetime):
            return timestamp_value
        
        if isinstance(timestamp_value, str):
            # 尝试不同的时间格式
            formats = [
                "%Y-%m-%d %H:%M:%S",
                "%Y-%m-%d %H:%M:%S.%f",
                "%Y%m%d %H%M%S",
                "%Y-%m-%d",
                "%Y%m%d"
            ]
            
            for fmt in formats:
                try:
                    return datetime.strptime(timestamp_value, fmt)
                except ValueError:
                    continue
        
        # 如果都失败了，返回当前时间
        return datetime.now()
    
    async def batch_convert(self, raw_data_list: List[Dict[str, Any]], 
                           data_type: str, source_format: str = "raw") -> List[Any]:
        """
        批量转换数据
        
        Args:
            raw_data_list: 原始数据列表
            data_type: 数据类型 (tick, bar, contract)
            source_format: 源数据格式
            
        Returns:
            List: 转换后的数据列表
        """
        converted_data = []
        
        for raw_data in raw_data_list:
            try:
                if data_type == "tick":
                    converted = await self.convert_tick_data(raw_data, source_format)
                elif data_type == "bar":
                    converted = await self.convert_bar_data(raw_data, source_format)
                elif data_type == "contract":
                    converted = await self.convert_contract_data(raw_data, source_format)
                else:
                    self.logger.warning(f"不支持的数据类型: {data_type}")
                    continue
                
                if converted:
                    converted_data.append(converted)
                    
            except Exception as e:
                self.logger.error(f"批量转换失败: {e}")
                continue
        
        return converted_data
    
    def add_field_mapping(self, source_format: str, mapping: Dict[str, str]) -> None:
        """添加字段映射"""
        self.default_mappings[source_format] = mapping
        self.logger.info(f"添加字段映射: {source_format}")
    
    def get_supported_formats(self) -> List[str]:
        """获取支持的格式"""
        return list(self.default_mappings.keys())
    
    async def health_check(self) -> Dict[str, Any]:
        """健康检查"""
        try:
            return {
                "status": "healthy",
                "converter": "RedFireDataConverter",
                "supported_formats": self.get_supported_formats(),
                "config": {
                    "source_format": self.config.source_format,
                    "target_format": self.config.target_format,
                    "data_validation": self.config.data_validation
                }
            }
        except Exception as e:
            return {
                "status": "unhealthy",
                "converter": "RedFireDataConverter",
                "error": str(e)
            }


# 全局数据转换器实例
_data_converter: Optional[RedFireDataConverter] = None


def get_data_converter() -> RedFireDataConverter:
    """获取全局数据转换器实例"""
    global _data_converter
    if _data_converter is None:
        _data_converter = RedFireDataConverter()
    return _data_converter
